﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using CargaDeDatos;
using CargaDeDatos.Data;
using CargaDeDatos.Data.CARGADataSetTableAdapters;
using System.IO;
using Aga.Psad.Mvc.Services.Dtos;
using System.Diagnostics;

namespace CargaDeDatos
{
    public partial class MainForm : Form
    {
        FileStream logFile;
        StreamWriter logger;

        Dictionary<int, ClienteDto> declarantes;
        Dictionary<int, List<ClienteDeClienteDto>> importadores;
        List<DespachoDto> despachos;

        public MainForm()
        {
            InitializeComponent();

            Reset();

            var logName = String.Format("Log.{0}.txt", DateTime.Now.ToString("yyyyMMdd"));
            logFile = new FileStream(logName, FileMode.Create);
            logger = new StreamWriter(logFile);
        }

        private void Reset()
        {
            declarantes = new Dictionary<int, ClienteDto>();
            importadores = new Dictionary<int, List<ClienteDeClienteDto>>();
            despachos = new List<DespachoDto>();

        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            try
            {
                using (var service = new UploadDataServiceClient())
                {
                    if (service.CheckService())
                        DisplayMessage("El servicio de carga de datos está online.");
                }
            }
            catch (Exception ex)
            {
                Log(ex.Message, LogType.Error);
            }

        }

        private void LeerClientes(CARGADataSet dataset)
        {
            bool hasErrors = false;
            // Declarantes
            DECLARANTESTableAdapter adapter = new DECLARANTESTableAdapter();
            CARGADataSet.DECLARANTESDataTable datatable = dataset.DECLARANTES;
            adapter.Fill(datatable);
            DataTableReader reader = datatable.CreateDataReader();

            rtbLog.AppendText("Leyendo Declarantes...\n");
            int rows = datatable.Rows.Count;
            int count = 0;
            pgbProgress.Minimum = 0;
            pgbProgress.Maximum = rows;
            while (reader.Read())
            {
                count++;
                lblProgress.Text = String.Format("Leyendo Declarantes... ({0}/{1})", count, rows);
                lblProgress.Refresh();
                pgbProgress.Value = count;

                string id = string.Empty;
                string nombre = string.Empty;
                string cuit = string.Empty;

                try
                {
                    id = reader.GetString(2).Trim();
                    nombre = reader.GetString(1).Trim();
                    cuit = reader.GetString(0).Trim();

                    ClienteDto declarante;
                    int exId = Int32.Parse(id);

                    declarante = GetClienteByExId(exId);

                    if (declarante == null)
                    {
                        declarante = new ClienteDto
                        {
                            ExId = exId,
                            RazonSocial = nombre,
                            Cuit = cuit
                        };

                        declarantes.Add(declarante.ExId, declarante);

                        string log = String.Format("Leído cliente ID:{0} - CUIT: {1} - NOMBRE: {2}\n", id, cuit, nombre);
                        Log(log, LogType.Info);
                    }
                    else
                    {
                        declarantes.Add(declarante.ExId, declarante);
                        string log = String.Format("Ya existe cliente ID:{0} - CUIT: {1} - NOMBRE: {2}\n", id, cuit, nombre);
                        Log(log, LogType.Info);
                    }

                }
                catch (Exception ex)
                {
                    string log = String.Format("ERROR leyendo cliente ID:{0} - CUIT: {1} - NOMBRE: {2}\n\tError: {3}\n", id, cuit, nombre, ex.Message);
                    Log(log, LogType.Error);
                    hasErrors = true;
                }
            }

            Log(String.Format("Clientes importados {0} errores.\n", (hasErrors ? "con" : "sin")), LogType.Error);
            hasErrors = false;

            // Importadores
            RAZONES_SOCIALESTableAdapter adapter2 = new RAZONES_SOCIALESTableAdapter();
            CARGADataSet.RAZONES_SOCIALESDataTable datatable2 = dataset.RAZONES_SOCIALES;
            adapter2.Fill(datatable2);
            reader = datatable2.CreateDataReader();

            rows = datatable2.Rows.Count;
            count = 0;
            pgbProgress.Minimum = 0;
            pgbProgress.Maximum = rows;

            rtbLog.AppendText("\nLeyendo Importadores...\n");
            while (reader.Read())
            {
                count++;
                lblProgress.Text = String.Format("Leyendo Importadores... ({0}/{1})", count, rows);
                lblProgress.Refresh();
                pgbProgress.Value = count;

                int declaranteId = reader.GetInt32(0);
                string cuit = reader.GetString(1).Trim();
                string razonsocial = reader.GetString(2).Trim();
                int id = reader.GetInt32(3);

                ClienteDeClienteDto importador;

                try
                {
                    importador = GetImportadorByExId(id);
                    if (importador == null)
                    {
                        importador = new ClienteDeClienteDto
                        {
                            ExId = id,
                            RazonSocial = razonsocial,
                            Cuit = cuit
                        };

                        ClienteDto declarante;
                        if (declarantes.ContainsKey(declaranteId))
                            declarante = declarantes[declaranteId];
                        else
                        {
                            declarante = GetClienteByExId(declaranteId);
                        }

                        if (declarante == null)
                        {
                            string log = String.Format("No se encontró el declarante ID:{0} para el cliente CLIENTE: ({1}) {2}\n", declaranteId, id, razonsocial);
                            Log(log, LogType.Info);
                        }
                        else
                        {
                            List<ClienteDeClienteDto> list;
                            if (importadores.ContainsKey(declaranteId))
                                list = importadores[declaranteId];
                            else
                            {
                                list = new List<ClienteDeClienteDto>();
                                importadores.Add(declaranteId, list);
                            }
                            list.Add(importador);

                            string log = String.Format("Leído importador ID:{0} - CUIT: {1} - RAZON SOCIAL: {2} - CLIENTE: ({3}) {4}\n", id, cuit, razonsocial, declarante.Id, declarante.RazonSocial);
                            Log(log, LogType.Info);
                        }
                    }
                    else
                    {
                        string log = String.Format("Ya existe importador ID:{0} - CUIT: {1} - RAZON SOCIAL: {2}\n", id, cuit, razonsocial);
                        Log(log, LogType.Info);
                    }
                }
                catch (Exception ex)
                {
                    string log = String.Format("ERROR leyendo importador ID:{0} - CUIT: {1} - NOMBRE: {2} - Cliente: {4}\n\tError: {3}\n", id, cuit, razonsocial, ex.Message, declaranteId);
                    Log(log, LogType.Error);
                    hasErrors = true;
                }
            }
            Log(String.Format("Importadores cargados {0} errores.\n", (hasErrors ? "con" : "sin")), LogType.Error);
        }

        private void LeerDespachos(CARGADataSet dataset)
        {
            UploadDataServiceClient service = null;
            bool hasErrors = false;
            CARGA_NUEVATableAdapter adapter = new CARGA_NUEVATableAdapter();
            CARGADataSet.CARGA_NUEVADataTable datatable = dataset.CARGA_NUEVA;
            adapter.Fill(datatable);
            DataTableReader reader = datatable.CreateDataReader();

            rtbLog.AppendText("\nLeyendo Despachos...\n");

            string actual = string.Empty;
            string familias = string.Empty;

            int rows = datatable.Rows.Count;
            int count = 0;
            pgbProgress.Minimum = 0;
            pgbProgress.Maximum = rows;

            try
            {
                service = new UploadDataServiceClient();

                string expediente = string.Empty;
                string familia = string.Empty;
                int caja = 0;
                string cuitDeclarante = string.Empty;
                string nombreDeclarante = string.Empty;
                string cuitImportador = string.Empty;
                string nombreImportador = string.Empty;
                string idCliente = string.Empty;
                int anio = 0;
                string f3101 = string.Empty;
                DateTime? fechaSeti = null;
                string observaciones = string.Empty;

                while (reader.Read())
                {
                    count++;
                    lblProgress.Text = String.Format("Leyendo Despachos... ({0}/{1})", count, rows);
                    lblProgress.Refresh();
                    pgbProgress.Value = count;
                    pgbProgress.Refresh();

                    try
                    {
                        if (!reader.IsDBNull(5))
                            expediente = reader.GetString(5).Trim();

                        if (!reader.IsDBNull(6))
                            familia = reader.GetString(6);

                        if (expediente.Equals(actual))
                        {
                            familias += String.Format("|{0}", familia.Trim());
                            continue;
                        }
                        else if (actual != string.Empty || count == rows)
                        {
                            SubirDespacho(
                                actual, 
                                caja, 
                                cuitDeclarante, 
                                nombreDeclarante, 
                                cuitImportador, 
                                nombreImportador, 
                                idCliente, 
                                familias,
                                anio,
                                f3101,
                                fechaSeti,
                                observaciones,
                                service);
                        }

                        actual = expediente;
                        familias = familia;
                        caja = 0;
                        cuitDeclarante = string.Empty;
                        nombreDeclarante = string.Empty;
                        cuitImportador = string.Empty;
                        nombreImportador = string.Empty;
                        idCliente = string.Empty;
                        anio = 0;
                        f3101 = string.Empty;
                        fechaSeti = null;
                        observaciones = string.Empty;

                        if (!reader.IsDBNull(7))
                            anio = reader.GetInt32(7);

                        if (!reader.IsDBNull(9))
                            f3101 = reader.GetString(9);

                        if (!reader.IsDBNull(10))
                            fechaSeti = reader.GetDateTime(10);

                        if (!reader.IsDBNull(11))
                            observaciones = reader.GetString(11);

                        if (!reader.IsDBNull(8))
                            idCliente = reader.GetString(8).Trim();

                        if (!reader.IsDBNull(0))
                            caja = reader.GetInt32(0);

                        if (!reader.IsDBNull(1))
                            cuitDeclarante = reader.GetString(1).Trim();

                        if (!reader.IsDBNull(2))
                            nombreDeclarante = reader.GetString(2).Trim();

                        if (!reader.IsDBNull(3))
                            cuitImportador = reader.GetString(3).Trim();

                        if (!reader.IsDBNull(4))
                            nombreImportador = reader.GetString(4).Trim();

                    }
                    catch (Exception ex)
                    {
                        string log = String.Format("ERROR leyendo despacho EXPEDIENTE:{0} - DECLARANTE: {1}\n\tError: {2}\n", expediente, cuitDeclarante, ex.Message);
                        Log(log, LogType.Error);
                        hasErrors = true;
                    }
                }
            }
            finally
            {
                if (service != null && service.State != System.ServiceModel.CommunicationState.Closed)
                {
                    service.Close();
                }
            }

            Log(String.Format("Despachos importados {0} errores.\n", (hasErrors ? "con" : "sin")), LogType.Error);

        }

        private void SubirDespacho(
            string expediente, 
            int caja, 
            string cuitDeclarante, 
            string nombreDeclarante, 
            string cuitImportador, 
            string nombreImportador, 
            string idCliente,
            string familias,
            int anio,
            string f3101,
            DateTime? fechaSeti,
            string observaciones,
            UploadDataServiceClient service)
        {
            DespachoDto despacho;

            despacho = GetDespachoByLegajo(expediente);

            if (despacho == null)
            {

                despacho = new DespachoDto()
                {
                    Caja = caja,
                    Legajo = expediente,
                    Familias = familias,
                    Anio = anio,
                    F3101 = f3101,
                    FechaSeti = fechaSeti,
                    Observaciones = observaciones
                };

                ClienteDto declarante = GetClienteByExId(Convert.ToInt32(idCliente));
                if (declarante == null)
                {
                    declarante = new ClienteDto
                    {
                        Cuit = cuitDeclarante,
                        ExId = Convert.ToInt32(idCliente),
                        RazonSocial = nombreDeclarante
                    };

                    //using (var service = new UploadDataServiceClient())
                    //{
                    declarante.Id = service.NuevoDeclarante(declarante);
                    despacho.DeclaranteId = declarante.Id;
                    //}


                    Log(String.Format("Se agregó el declarante CUIT:{0} - RAZON SOCIAL: {1}\n", cuitDeclarante, nombreDeclarante), LogType.Info);
                }
                else
                    despacho.DeclaranteId = declarante.Id;

                ClienteDeClienteDto importador = GetImportadorByCuit(Convert.ToInt32(idCliente), cuitImportador);

                if (importador == null)
                {
                    importador = new ClienteDeClienteDto
                    {
                        Cuit = cuitImportador,
                        RazonSocial = nombreImportador,
                        ClienteId = declarante.Id
                    };
                    //using (var service = new UploadDataServiceClient())
                    //{
                        despacho.ImportadorId = service.NuevoImportador(importador);
                    //}

                    Log(String.Format("Se agergó el importador CUIT:{0} - RAZON SOCIAL: {1}\n", cuitImportador, nombreImportador), LogType.Info);
                }
                else
                    despacho.ImportadorId = importador.Id;

                //using (var service = new UploadDataServiceClient())
                //{
                    service.NuevoDespacho(despacho);
                //}

                Log(String.Format("Cargado correctamente el despacho EXPEDIENTE:{0} - FAMILIAS:{2} - DECLARANTE: {1}\n", expediente, cuitDeclarante, familias), LogType.Info);
            }
            else
            {
                bool actualizar = false;
                string[] arrayFamilias = familias.Split('|');

                foreach (var familia in arrayFamilias)
                {
                    if (!despacho.Familias.Contains(familia))
                    {
                        despacho.Familias += String.Format("|{0}", familia);
                        actualizar = true;
                    }
                }

                if (actualizar)
                {
                    service.ActualizarDespacho(despacho);

                    string log = String.Format("Se actualizó el despacho EXPEDIENTE:{0} - FAMILIAS:{1} - DECLARANTE: {1}\n", expediente, cuitDeclarante, familias);

                    Log(log, LogType.Info);
                }
            }
        }

        private ClienteDeClienteDto GetImportadorByCuit(int clienteExId, string cuitImportador)
        {
            using (var service = new UploadDataServiceClient())
            {
                ClienteDeClienteDto cliente = service.ObtenerImportadorPorCuit(clienteExId, cuitImportador);
                return cliente;
            }
        }

        private ClienteDeClienteDto GetImportadorByExId(int exId)
        {
            using (var service = new UploadDataServiceClient())
            {
                ClienteDeClienteDto cliente = service.ObtenerImportadorPorExId(exId);
                return cliente;
            }
        }

        private ClienteDto GetClienteByExId(int exId)
        {
            using (var service = new UploadDataServiceClient())
            {
                ClienteDto cliente = service.ObtenerDeclarantePorExId(exId);
                return cliente;
            }
        }

        private DespachoDto GetDespachoByLegajo(string expediente)
        {
            using (var service = new UploadDataServiceClient())
            {
                DespachoDto despacho = service.ObtenerDespachoPorLegajo(expediente);
                return despacho;
            }
        }

        private void btnSalir_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void btnIniciar_Click(object sender, EventArgs e)
        {
            try
            {
                Log("\nIniciando carga de datos...\n\n", LogType.Info);

                CARGADataSet dataset = new CARGADataSet();

                if (chkClientes.Checked)
                {
                    LeerClientes(dataset);

                    ImportarClientes();

                }
                if (chkDespachos.Checked)
                {
                    LeerDespachos(dataset);
                }

                Reset();

                lblProgress.Text = "Proceso Completado.";

                MessageBox.Show(
                    "Processo Completado",
                    "Importación de Datos",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Information);

            }
            catch (Exception ex)
            {
                Log(ex.Message, LogType.Error);
            }
        }

        private void ImportarClientes()
        {
            using (var service = new UploadDataServiceClient())
            {
                foreach (var declarante in declarantes.Values)
                {
                    if (declarante.Id == 0)
                    {
                        int id = service.NuevoDeclarante(declarante);
                        declarante.Id = id;
                    }

                    if (importadores.ContainsKey(declarante.ExId))
                    {
                        foreach (var importador in importadores[declarante.ExId])
                        {
                            if (importador.Id == 0)
                            {
                                importador.ClienteId = declarante.Id;
                                int id = service.NuevoImportador(importador);
                            }
                        }
                    }
                }
            }
        }

        private void Log(string log, LogType type)
        {
            if ((rdbSoloErrores.Checked && type == LogType.Error) || rdbTodos.Checked)
            {
                DisplayMessage(log);
            }
            logger.WriteLine(DateTime.Now.ToLocalTime() + ": " + log);
        }

        private void DisplayMessage(string log)
        {
            rtbLog.AppendText(log);
            rtbLog.ScrollToCaret();
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            var dg = MessageBox.Show(
                "Confirma que desea salir?",
                "Salir",
                MessageBoxButtons.YesNo,
                MessageBoxIcon.Question,
                MessageBoxDefaultButton.Button2);

            if (dg == DialogResult.No)
            {
                e.Cancel = true;
            }
            else
            {
                logger.Flush();
                logger.Close();
            }

        }
    }

    internal enum LogType
    {
        Info,
        Error
    }

}
